/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.udt.designtime.api.converter;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.inspur.edp.udt.designtime.api.entity.ComplexDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import com.inspur.edp.udt.designtime.api.utils.Context;
import com.inspur.edp.udt.designtime.api.utils.UdtThreadLocal;

import io.iec.edp.caf.commons.exception.CAFRuntimeException;
import java.io.IOException;

/**
 * UDT转换器
 */
public class UnifiedDataTypeDefConverter {
    String serializeResult = "{\n" +
        "    \"Type\": \"SimpleDataType\",\n" +
        "    \"Content\": {}}";
    String simpleUdtType = "SimpleDataType";
    String complexUdtType = "ComplexDataType";
    String para_Type = "Type";
    String para_Content = "Content";

    /**
     * UDT转换为数据库列信息
     *
     * @param unifiedDataTypeDef UDT
     * @return 数据库列信息
     */
    public String convertToDatabaseColumn(UnifiedDataTypeDef unifiedDataTypeDef) {
        Context context = new Context();
        context.setfull(false);
        UdtThreadLocal.set(context);
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode result = mapper.readTree(serializeResult);
            if (unifiedDataTypeDef.getClass().isAssignableFrom(SimpleDataTypeDef.class)) {
                String jsonResult = mapper.writeValueAsString((SimpleDataTypeDef) unifiedDataTypeDef);
                ((ObjectNode) result).put(para_Type, simpleUdtType);
                JsonNode sUdtJson = mapper.readTree(jsonResult);
                ((ObjectNode) result).set(this.para_Content, sUdtJson);
                return result.toString();
            } else if (unifiedDataTypeDef.getClass().isAssignableFrom(ComplexDataTypeDef.class)) {
                String jsonResult = mapper.writeValueAsString((ComplexDataTypeDef) unifiedDataTypeDef);
                ((ObjectNode) result).put(para_Type, complexUdtType);
                JsonNode cUdtJson = mapper.readTree(jsonResult);
                ((ObjectNode) result).set(this.para_Content, cUdtJson);
                return result.toString();
            } else {
                throw new CAFRuntimeException("", "", "udt序列化器无法序列化当前类型：" + unifiedDataTypeDef.getClass().getTypeName(), new RuntimeException());
            }
        } catch (IOException e) {
            throw new CAFRuntimeException("", "", "udt元数据'" + ((UnifiedDataTypeDef) unifiedDataTypeDef).getName() + "'序列化报错。" + e.getMessage(), e);
        }
    }

    /**
     * 转换为UDT类型
     *
     * @param json UDT Json
     * @return UDT类型
     */
    public UnifiedDataTypeDef convertToEntityAttribute(String json) {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode = null;
        try {
            jsonNode = mapper.readTree(json);
        } catch (IOException e) {
            throw new CAFRuntimeException("", "", e.getMessage(), e);
        }
        String componentType = jsonNode.get(para_Type).textValue();
        String dataType = jsonNode.get(para_Content).toString();
        if (complexUdtType.equals(componentType)) {
            try {
                ComplexDataTypeDef complexDataTypeDef = mapper.readValue(dataType, ComplexDataTypeDef.class);
                complexDataTypeDef.updateColumnsInfo();
                return complexDataTypeDef;
            } catch (IOException e) {
                throw new CAFRuntimeException("", "","反序列化多值udt异常！" + e, e);
            }
        }
        if (simpleUdtType.equals(componentType)) {
            try {
                SimpleDataTypeDef simpleDataTypeDef = mapper.readValue(dataType, SimpleDataTypeDef.class);
                simpleDataTypeDef.updateColumnsInfo();
                return simpleDataTypeDef;
            } catch (IOException e) {
                throw new CAFRuntimeException("","", "反序列化单值udt异常！" + e, e);
            }
        }
        return null;
    }
}
